PedigreeExport = function () {
};

PedigreeExport.prototype = {
};

PedigreeExport.exportAsSimpleJSON = function(pedigree, privacySetting)
{
   var exportObj = [];
    var getMotherFather = function(nodeID) {
         // mother & father
         var parents = pedigree.GG.getParents(nodeID);
         if (parents.length > 0) {
             var father = parents[0];
             var mother = parents[1];
             if ( pedigree.GG.properties[parents[0]]["gender"] == "F" ||
                  pedigree.GG.properties[parents[1]]["gender"] == "M" ) {
                 father = parents[1];
                 mother = parents[0];
             }
         }
         return {"mother": mother, "father": father};
     };

     var idToJSONId = PedigreeExport.createNewIDs(pedigree);
     

   for (var i = 0; i <= pedigree.GG.getMaxRealVertexId(); i++) {
       if (!pedigree.GG.isPerson(i)) continue;

       var person = {"id": i};
       var parents = pedigree.GG.getParents(i);
       if (parents.length > 0) {
           var father = parents[0];
           var mother = parents[1];

           if ( pedigree.GG.properties[parents[0]]["gender"] == "F" ||
                pedigree.GG.properties[parents[1]]["gender"] == "M" ) {
               father = parents[1];
               mother = parents[0];
           }
           person["father"] = father;
           person["mother"] = mother;
       }

       var properties = pedigree.GG.properties[i];
       for (var property in properties) {
           if (properties.hasOwnProperty(property)) {
               if (privacySetting != "all") {
                   if (property == 'lName' || property == 'fName' || property == 'lNameAtB' ||
                       property == 'dob' || property == 'bob') continue;
                   if (privacySetting == "minimal" && property == "comments") continue
               }
               var converted = PedigreeExport.convertProperty(property, properties[property]);
               if (converted !== null) {
                   person[converted.propertyName] = converted.value;
               }
           }
       }

        if (editor.getGraph().getProbandId() == i) {
             person["proband"] = true;
         }
       exportObj.push(person);
   }

    var nextRelId = 1;
     for (var i = 0; i <= pedigree.GG.getMaxRealVertexId(); i++) {
         if (!pedigree.GG.isRelationship(i)) continue;
         
      var person = {"id": i};
      
         var relationship = {"relationshipId": nextRelId++};

         var properties = pedigree.GG.properties[i];
         var hasProperties = false;
         for (var property in properties) {
             if (properties.hasOwnProperty(property)) {
                 hasProperties = true;
                 var converted = PedigreeExport.convertRelationshipProperty(property, properties[property]);
                 if (converted !== null) {
                     relationship[converted.propertyName] = converted.value;
                 }
             }
         }

         if (!hasProperties) {
             continue;
         }
       var parents = pedigree.GG.getParents(i);
       if (parents.length > 0) {
           var father = parents[0];
           var mother = parents[1];

           if ( pedigree.GG.properties[parents[0]]["gender"] == "F" ||
                pedigree.GG.properties[parents[1]]["gender"] == "M" ) {
               father = parents[1];
               mother = parents[0];
           }
           relationship["partner1"] = father;
           relationship["partner2"] = mother;
       }
           
         exportObj.push(relationship);
     }
   return JSON.stringify(exportObj);
}
/*
 *  PDF format
*/

PedigreeExport.exportAsPED = function(pedigree, idGenerationPreference)
{
   var output = "";

   var familyID = XWiki.currentDocument.page;

   var idToPedId = PedigreeExport.createNewIDs(pedigree, idGenerationPreference);

   for (var i = 0; i <= pedigree.GG.getMaxRealVertexId(); i++) {
       if (!pedigree.GG.isPerson(i)) continue;

       output += familyID + " " + idToPedId[i] + " ";

       var parents = pedigree.GG.getParents(i);
       if (parents.length > 0) {
           var father = parents[0];
           var mother = parents[1];

           if ( pedigree.GG.properties[parents[0]]["gender"] == "F" ||
                pedigree.GG.properties[parents[1]]["gender"] == "M" ) {
               father = parents[1];
               mother = parents[0];
           }
           output += idToPedId[father] + " " + idToPedId[mother] + " ";
       } else {
           output += "0 0 ";
       }

       var sex = 3;
       if (pedigree.GG.properties[i]["gender"] == "M") {
           sex = 1;
       }
       else if (pedigree.GG.properties[i]["gender"] == "F") {
           sex = 2;
       }
       output += (sex + " ");

       var status = -9; 
       if (pedigree.GG.properties[i].hasOwnProperty("carrierStatus")) {
           if (pedigree.GG.properties[i]["carrierStatus"] == "affected" ||
               pedigree.GG.properties[i]["carrierStatus"] == "carrier"  ||
               pedigree.GG.properties[i]["carrierStatus"] == "presymptomatic")
               status = 2;
           else
               status = 1;
       }
       output += status + "\n";
   }

   return output;
}


PedigreeExport.exportAsBOADICEA = function(pedigree, idGenerationPreference)
{
   var output = "BOADICEA import pedigree file format 2.0\n";
   output    += "FamilyID\tName\tTarget\tIndivID\tFathID\tMothID\tSex\tTwin\tDead\tAge\tYob\tNot_implemented_yet_except_Ahkenazi\n";

   var familyID = XWiki.currentDocument.page;

   var idToBoadId = PedigreeExport.createNewIDs(pedigree, idGenerationPreference, 7 /* max ID length */);

   var alertUnknownGenderFound = false; // BOADICEA does not support unknown genders

   for (var i = 0; i <= pedigree.GG.getMaxRealVertexId(); i++) {
       if (!pedigree.GG.isPerson(i)) continue;

       var id = idToBoadId[i];

       var name = pedigree.GG.properties[i].hasOwnProperty("fName") ? pedigree.GG.properties[i]["fName"].substring(0,8) : id;

       var proband = (i == 0) ? "1" : "0";

       output += familyID + "\t" + name + "\t" + proband + "\t" + id + "\t";

       // mother & father
       var parents = pedigree.GG.getParents(i);
       if (parents.length > 0) {
           var father = parents[0];
           var mother = parents[1];

           if ( pedigree.GG.properties[parents[0]]["gender"] == "F" ||
                pedigree.GG.properties[parents[1]]["gender"] == "M" ) {
               father = parents[1];
               mother = parents[0];
           }
           output += idToBoadId[father] + "\t" + idToBoadId[mother] + "\t";
       } else {
           output += "0\t0\t";
       }

       var sex = "M";
       if (pedigree.GG.properties[i]["gender"] == "F") {
           sex = "F";
       } else if (pedigree.GG.properties[i]["gender"] == "U") {
           alertUnknownGenderFound = true;
       }
       output += sex + "\t";

       if (pedigree.GG.getTwinGroupId(i) !== null) {
           output += "1\t";
       } else {
           output += "0\t";
       }

       var dead = "0";
       if (pedigree.GG.properties[i].hasOwnProperty("lifeStatus")) {
           if (pedigree.GG.properties[i]["lifeStatus"] != "alive") {
               var dead = "1";
           }
       }
       output += dead + "\t";

       var age = "0";
       var yob = "0";
       if (pedigree.GG.properties[i].hasOwnProperty("dob")) {
           var date = new Date(pedigree.GG.properties[i]["dob"]);
           yob = date.getFullYear();
           age = new Date().getFullYear() - yob;
       }
       output += age + "\t" + yob + "\t";

       output += "AU\tAU\tAU\tAU\tAU\t";   

       output += "0\t0\t";                 

       var ashkenazi = "0";
       if (pedigree.GG.properties[i].hasOwnProperty("ethnicities")) {
           var ethnicities = pedigree.GG.properties[i]["ethnicities"];
           for (var k = 0; k < ethnicities.length; k++) {
               if (ethnicities[k].match(/ashkenaz/i) !== null) {
                   ashkenazi = "1";
                   break;
               }
           }
       }
       output += ashkenazi + "\t";

       output += "0\t0\t0\t0\t0";  

       output += "\n";
   }

   if (alertUnknownGenderFound) {
       alert("BOADICEA format does not support unknown genders. All persons of unknown gender were saved as male in the export file");
   }

   return output;
}

// ===============================================================================================

PedigreeExport.internalToJSONPropertyMapping = {
        "proband":       "proband",
        "fName":         "firstName",
        "lName":         "lastName",
        "lNameAtB":      "lastNameAtBirth",
        "comments":      "comments",
        "twinGroup":     "twinGroup",
        "monozygotic":   "monozygotic",
        "unknownzygotic": "unknownzygotic",
        "isAdopted":     "adoptedIn",
        "evaluated":     "evaluated",
        "dob":           "birthDate",
        "dod":           "deathDate",
        "gestationAge":  "gestationAge",
        "lifeStatus":    "lifeStatus",
        "disorders":     "disorders",
        "ethnicities":   "ethnicities",
        "carrierStatus": "carrierStatus",
        "externalID":    "externalId",
        "gender":        "sex",
        "numPersons":    "numPersons",
        "hpoTerms":      "hpoTerms",
        "candidateGenes":"candidateGenes",
        "lostContact":   "lostContact",
        "nodeNumber":    "nodeNumber",
        "evaluatedinfo":    					"evaluatedinfo",
        "childlessReason":    				"childlessReason",
        "rareTumorName":    					"rareTumorName",
        "otherTumorName":    				"otherTumorName",
        "gastrointestinalTumorName":    		"gastrointestinalTumorName",
        "urogenitalTumorName":    			"urogenitalTumorName",
        "highRelativeCancerName":    		"highRelativeCancerName",
        "cancerTypes":    					"cancerTypes",
        "cancerAgeNum":    					"cancerAgeNum",
        "cancerAgeType":    					"cancerAgeType",
        "probability":    					"probability",
        "deceasedText":    					"deceasedText",
        "deathAge":    						"deathAge",
        "curentAge":    						"curentAge",
        "ethnicityName":    					"ethnicityName",
        "bornAddr":    						"bornAddr",
        "telNum":    						"telNum",
        "dateOfAdd":    						"dateOfAdd",
        "consangr":    						"consangr",
        "broken":    						"broken",
        "childlessStatus": 					"childlessStatus",
        "childlessReason": 					"childlessReason",
        "memberID":"memberID",
        "cancer":"cancer",
        "precursor":"precursor",
        "familyUserId":"familyUserId",
        "id":"id"
    };
PedigreeExport.internalToJSONRelationshipPropertyMapping = {
          "childlessStatus": "childlessStatus",
          "childlessReason": "childlessReason",
          "consangr":        "consanguinity",
          "broken":          "separated"
      };


PedigreeExport.convertProperty = function(internalPropertyName, value) {
    if (!PedigreeExport.internalToJSONPropertyMapping.hasOwnProperty(internalPropertyName))
        return null;

    var externalPropertyName = PedigreeExport.internalToJSONPropertyMapping[internalPropertyName];

    if (externalPropertyName == "sex") {
        if (value == "M")
            value = "male";
        else if (value == "F")
            value = "female";
        else
            value = "unknown";
    }

    return {"propertyName": externalPropertyName, "value": value };
}

PedigreeExport.convertRelationshipProperty = function(internalPropertyName, value) {

      if (!PedigreeExport.internalToJSONRelationshipPropertyMapping.hasOwnProperty(internalPropertyName)) {
          return null;
      }

      var externalPropertyName = PedigreeExport.internalToJSONRelationshipPropertyMapping[internalPropertyName];

      if (externalPropertyName == "consanguinity") {
          if (value != "Y" && value != "N"&& value != "E") {
              return null;
          }
      }
      return {"propertyName": externalPropertyName, "value": value };
  }
 PedigreeExport.guessPossibleGender = function(dynamicPedigree, v)
  {
        var possible = {"M": true, "F": true};

        var partners = dynamicPedigree.DG.GG.getAllPartners(v);

        for (var i = 0; i < partners.length; i++) {
            var partnerGender = dynamicPedigree.getGender(partners[i]);
            if (partnerGender != "U" && partnerGender != "O") {
                possible[partnerGender] = false;
            }
        }
        return possible;
 }
PedigreeExport.createNewIDs = function(pedigree, idGenerationPreference, maxLength) {
    var idToNewId = {};
    var usedIDs   = {};

    var nextUnusedID = 1;

    for (var i = 0; i <= pedigree.GG.getMaxRealVertexId(); i++) {
        if (!pedigree.GG.isPerson(i)) continue;

        var id = nextUnusedID++;
        if (idGenerationPreference == "external" && pedigree.GG.properties[i].hasOwnProperty("externalID")) {
            nextUnusedID--;
            id = pedigree.GG.properties[i]["externalID"].replace(/\s/g, '_');
        } else if (idGenerationPreference == "name" && pedigree.GG.properties[i].hasOwnProperty("fName")) {
            nextUnusedID--;
            id = pedigree.GG.properties[i]["fName"].replace(/\s/g, '_');
        }
        if (maxLength && id.length > maxLength) {
            id = id.substring(0, maxLength);
        }
        while ( usedIDs.hasOwnProperty(id) ) {
            if (!maxLength || id.length < maxLength) {
                id = "_" + id;
            } else {
                id = nextUnusedID++;
            }
        }

        idToNewId[i] = id;
        usedIDs[id]  = true;
    }

    return idToNewId;
}
